using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using OracleInternal.Json.Common;
using OracleInternal.Json.Sql;

namespace OracleInternal.Json.Binary
{
	internal class OsonArray : OsonAbstractArray, IOracleJsonArray, IOracleJsonStructure, IOracleJsonValue, IList<OracleJsonValue>, ICollection<OracleJsonValue>, IEnumerable<OracleJsonValue>, IEnumerable, IEnumerator<OracleJsonValue>, IEnumerator, IDisposable
	{
		private int m_iter = -1;

		public int Count => m_size;

		public bool IsReadOnly => false;

		public OracleJsonValue this[int index]
		{
			get
			{
				return (OracleJsonValue)GetInternal(index);
			}
			set
			{
				throw CreateNotModifiable();
			}
		}

		public OracleJsonValue Current => (OracleJsonValue)GetInternal(m_iter);

		object IEnumerator.Current => (OracleJsonValue)GetInternal(m_iter);

		internal OsonArray(OsonContext ctx, int pos)
			: base(ctx, pos)
		{
		}

		public override string ToJsonString()
		{
			StringWriter stringWriter = new StringWriter();
			OracleJsonSerializer oracleJsonSerializer = new OracleJsonSerializer(stringWriter);
			oracleJsonSerializer.Write(this);
			oracleJsonSerializer.Close();
			return stringWriter.ToString();
		}

		internal double GetDouble(int index)
		{
			int offsetWithError = GetOffsetWithError(index);
			return ((OracleJsonNumber)GetValueInternal(offsetWithError)).DoubleValue();
		}

		internal decimal GetBigDecimal(int index)
		{
			int offsetWithError = GetOffsetWithError(index);
			return ((OracleJsonNumber)GetValueInternal(offsetWithError)).BigDecimalValue();
		}

		internal long GetLong(int index)
		{
			int offsetWithError = GetOffsetWithError(index);
			return ((OracleJsonNumber)GetValueInternal(offsetWithError)).LongValue();
		}

		internal DateTime GetDateTime(int index)
		{
			int offsetWithError = GetOffsetWithError(index);
			OracleJsonValue oracleJsonValue = (OracleJsonValue)GetValueInternal(offsetWithError);
			return oracleJsonValue.GetOracleJsonType() switch
			{
				OracleJsonType.TIMESTAMP => ((OracleJsonTimestamp)oracleJsonValue).GetDateTime(), 
				OracleJsonType.DATE => ((OracleJsonDate)oracleJsonValue).GetDateTime(), 
				_ => throw new InvalidCastException(), 
			};
		}

		internal byte[] GetBytes(int index)
		{
			int offsetWithError = GetOffsetWithError(index);
			return ((OracleJsonBinary)GetValueInternal(offsetWithError)).GetBytes();
		}

		internal OracleJsonValue Set(int index, OracleJsonValue element)
		{
			throw CreateNotModifiable();
		}

		internal void Add(int index, OracleJsonValue element)
		{
			throw CreateNotModifiable();
		}

		internal OracleJsonValue Remove(int index)
		{
			throw CreateNotModifiable();
		}

		internal OracleJsonValue Set(int index, string value)
		{
			throw CreateNotModifiable();
		}

		internal void Add(string value)
		{
			throw CreateNotModifiable();
		}

		internal OracleJsonValue Set(int index, int value)
		{
			throw CreateNotModifiable();
		}

		internal void Add(int value)
		{
			throw CreateNotModifiable();
		}

		internal OracleJsonValue Set(int index, double value)
		{
			throw CreateNotModifiable();
		}

		internal void Add(double value)
		{
			throw CreateNotModifiable();
		}

		internal OracleJsonValue Set(int index, bool value)
		{
			throw CreateNotModifiable();
		}

		internal void Add(bool value)
		{
			throw CreateNotModifiable();
		}

		internal OracleJsonValue SetNull(int index)
		{
			throw CreateNotModifiable();
		}

		internal void AddNull()
		{
			throw CreateNotModifiable();
		}

		internal OracleJsonValue Set(int index, DateTime value)
		{
			throw CreateNotModifiable();
		}

		internal void Add(DateTime value)
		{
			throw CreateNotModifiable();
		}

		internal OracleJsonValue Set(int index, byte[] value)
		{
			throw CreateNotModifiable();
		}

		internal void Add(byte[] value)
		{
			throw CreateNotModifiable();
		}

		internal OracleJsonValue Set(int index, long value)
		{
			throw CreateNotModifiable();
		}

		internal OracleJsonValue Set(int index, decimal value)
		{
			throw CreateNotModifiable();
		}

		internal void Add(long value)
		{
			throw CreateNotModifiable();
		}

		internal void Add(decimal value)
		{
			throw CreateNotModifiable();
		}

		private NotSupportedException CreateNotModifiable()
		{
			throw OracleJsonExceptions.ARR_NOT_MUTABLE.Create(OracleJsonExceptions.ORACLE_FACTORY);
		}

		public int IndexOf(OracleJsonValue item)
		{
			throw CreateNotModifiable();
		}

		public void Insert(int index, OracleJsonValue item)
		{
			throw CreateNotModifiable();
		}

		public void RemoveAt(int index)
		{
			throw CreateNotModifiable();
		}

		public void Add(OracleJsonValue item)
		{
			throw CreateNotModifiable();
		}

		public void Clear()
		{
			throw CreateNotModifiable();
		}

		public bool Contains(OracleJsonValue item)
		{
			throw CreateNotModifiable();
		}

		public void CopyTo(OracleJsonValue[] array, int arrayIndex)
		{
			throw CreateNotModifiable();
		}

		public bool Remove(OracleJsonValue item)
		{
			throw CreateNotModifiable();
		}

		public IEnumerator<OracleJsonValue> GetEnumerator()
		{
			return this;
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return this;
		}

		public void Dispose()
		{
		}

		public bool MoveNext()
		{
			if (m_iter < m_size - 1)
			{
				m_iter++;
				return true;
			}
			return false;
		}

		public void Reset()
		{
			m_iter = -1;
		}
	}
}
